import 'dart:collection';

import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_common/flutter_common.dart';
import 'package:flutter_common/util/logger.dart';
import 'package:flutter_common/util/string_utils.dart';
import 'package:flutter_common/util/toast_util.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:dio/dio.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:path_provider/path_provider.dart';


setWebContentsDebuggingEnabled(bool enabled) {
  if (SafePlatform.isAndroid() || SafePlatform.isOhos()) {
    // AndroidInAppWebViewController.setWebContentsDebuggingEnabled(enabled);
    InAppWebViewController.setWebContentsDebuggingEnabled(enabled);
  }
}

///如果使用h5录制视频，安卓需要配置 provider，及申请摄像头和录音权限
class SimpleWebView extends StatefulWidget {

  /// 显示的地址
  final String? url;
  /// 富文本格式的字符串
  final String? data;
  /// 本地的html文件
  final String? file;
  /// 是否使用下载加载链接
  final bool? useOnDownloadStart;
  /// 是否拦截广告
  final bool blockAd;

  const SimpleWebView({
    Key? key,
    this.url,
    this.data,
    this.file,
    this.blockAd = true,
    this.useOnDownloadStart
  }): super(key: key);

  @override
  State<SimpleWebView> createState() => SimpleWebViewState();

}

class SimpleWebViewState<T extends SimpleWebView> extends State<T> with FxState {

  ///将字符串拼接在原有的 userAgent后
  String userAgentAppend() => "";
  String? userAgent() => null;

  URLRequest? _initialUrl;
  final GlobalKey webViewKey = GlobalKey();
  InAppWebViewController? webViewController;

  late PullToRefreshController pullToRefreshController;
  /// [0 - 1]
  double _loadProgress = 0;

  bool get isLoadFinish => _loadProgress == 1;
  /// 网址需要添加的header
  Map<String, String>? _header;

  @override
  void initState() {
    super.initState();
    _initialUrl = buildURLRequest();
    printLogger("WebView url: $_initialUrl");

    pullToRefreshController = PullToRefreshController(
      // options: PullToRefreshOptions(
      //   color: Colors.blue,
      // ),
      settings: PullToRefreshSettings(color: Colors.blue),
      onRefresh: () async {
        if (SafePlatform.isAndroid()) {
          webViewController?.reload();
        } else if (SafePlatform.isIOS()) {
          webViewController?.loadUrl(
              urlRequest: URLRequest(url: await webViewController?.getUrl()));
        }
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        _webView(),
        _loadProgress < 1.0
            ? LinearProgressIndicator(
            value: _loadProgress.toDouble(), backgroundColor: Colors.blue)
            : Container(),
      ],
    );
  }

  _webView() {
    // InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
    //     crossPlatform: InAppWebViewOptions(
    //       useShouldOverrideUrlLoading: true,
    //       useOnDownloadStart: widget.useOnDownloadStart ?? true,
    //       applicationNameForUserAgent: userAgentAppend(),
    //       mediaPlaybackRequiresUserGesture: false,
    //     ),
    //     android: AndroidInAppWebViewOptions(
    //       useHybridComposition: true, //使用混合集成
    //       useShouldInterceptRequest: true,
    //       mixedContentMode: AndroidMixedContentMode.MIXED_CONTENT_ALWAYS_ALLOW,
    //       layoutAlgorithm: AndroidLayoutAlgorithm.NARROW_COLUMNS,
    //       initialScale: 1,
    //       loadWithOverviewMode: true,
    //       useWideViewPort: true,
    //     ),
    //     ios: IOSInAppWebViewOptions(
    //       allowsInlineMediaPlayback: true,
    //     ));
    InAppWebViewSettings settings = InAppWebViewSettings(
      mixedContentMode: MixedContentMode.MIXED_CONTENT_ALWAYS_ALLOW,
      useShouldOverrideUrlLoading: true,
      useOnDownloadStart: widget.useOnDownloadStart ?? true,
      applicationNameForUserAgent: userAgentAppend(),
      userAgent: userAgent(),
      mediaPlaybackRequiresUserGesture: false,
      useHybridComposition: true, //使用混合集成
      useShouldInterceptRequest: true,
      layoutAlgorithm: LayoutAlgorithm.NARROW_COLUMNS,
      initialScale: 1,
      loadWithOverviewMode: true,
      useWideViewPort: true,
      allowsInlineMediaPlayback: true,
    );
    return InAppWebView(
      key: webViewKey,
      // contextMenu: contextMenu,
      initialUrlRequest: _initialUrl,
      //h5的url
      initialData: requestData(),
      initialFile: widget.file,
      initialUserScripts: UnmodifiableListView<UserScript>([]),
      // initialOptions: options,
      initialSettings: settings,
      pullToRefreshController: pullToRefreshController,
      onProgressChanged: (controller, progress) {
        if (progress == 100) {
          pullToRefreshController.endRefreshing();
        }
        mountedState(() {
          _loadProgress = progress / 100;
        });
      },
      gestureRecognizers: {Factory(()=>EagerGestureRecognizer())}, //用于解决 webview与pageView手势冲突问题
      onWebViewCreated: _updateController,
      // androidOnPermissionRequest: (controller, origin, resources) async {
      //   return PermissionRequestResponse(
      //       resources: resources,
      //       action: PermissionRequestResponseAction.GRANT);
      // },
      onPermissionRequest: (controller, request) async {
        return PermissionResponse(
            resources: request.resources,
            action: PermissionResponseAction.GRANT);
      },
      onLoadStop: (controller, url) async {
        pullToRefreshController.endRefreshing();
        onLoadStop(url);
        mountedState();
      },
      // onLoadError: (controller, url, code, message) {
      //   printLogger("WebView load error: $code -- $message");
      //   pullToRefreshController.endRefreshing();
      // },
      onReceivedError: (controller, request, error) {
        printLogger("WebView load error: ${error.toString()}");
        pullToRefreshController.endRefreshing();
      },
      onTitleChanged: _onTitleChanged,
      onUpdateVisitedHistory: (controller, url, androidIsReload) {
        mountedState();
      },
      onConsoleMessage: (controller, consoleMessage) {
        printLogger(consoleMessage);
      },
      onScrollChanged: (controller, x, y) => onScrollChanged(x, y),
      shouldOverrideUrlLoading: (controller, navigationAction) async {
        var uri = navigationAction.request.url!;
        if (shouldOverrideUrlLoading(uri.toString())) {
          return NavigationActionPolicy.CANCEL;
        }
        if(_header != null) {
          navigationAction.request.headers = _header;
          controller.loadUrl(urlRequest: navigationAction.request);
          return NavigationActionPolicy.CANCEL;
        }
        return NavigationActionPolicy.ALLOW;
      },
      // androidShouldInterceptRequest: (controller, request) async {
      //   _header = (request.headers);
      // },
      shouldInterceptRequest: (controller, request) {
          _header = (request.headers);
          return shouldInterceptRequest(request);
      },
      onDownloadStartRequest: (controller, DownloadStartRequest request){
        onDownloadStartRequest(request);
      },
      onLongPressHitTestResult: (controller, hitTestResult) =>
          onLongPressHitTestResult(hitTestResult),
      onOverScrolled: (controller, x, y, clampedX, clampedY) =>
          onOverScrolled(x, y, clampedX, clampedY),
    );
  }

  bool shouldOverrideUrlLoading(String url) {
    return false;
  }

  void onDownloadStartRequest(DownloadStartRequest request) async {
    String? down = await getDownloadsPath();
    String path = "$down/${request.suggestedFilename}";

    ToastUtil.showToast("文件开始下载");
    Dio dio = Dio();
    dio.downloadUri(request.url, path, onReceiveProgress: (t,s){
      if(t == s) {
        ToastUtil.showToast("文件下载完成。$path", toastLength: Toast.LENGTH_LONG);
      }
    });
  }

  Future<WebResourceResponse?> shouldInterceptRequest(WebResourceRequest request) {
    if (widget.blockAd && isAds(request.url.host)) {
        return Future.value(WebResourceResponse(statusCode: 200));
    }
    return Future.value();
  }

  bool isAds(String path) {
    // logger.debug(path);
    if(path.endsWith('googlesyndication.com')) return true;
    return false;
  }

  URLRequest? buildURLRequest() {
    Uri? uri = requestUri();
    if(uri == null) return null;
    if(uri is WebUri) return URLRequest(url: uri);
    return URLRequest(url: WebUri.uri(uri));
  }

  ///构建一个完整的请求链接
  Uri? requestUri() {
    if(widget.url.isNullOrEmpty) return null;
    return Uri.parse(widget.url!);
  }

  String? buildData() {
    if(widget.data.isNullOrEmpty) return null;
    if(!widget.data!.startsWith("<html>")) { //解决富文本字体显示问题
      return """
            <html><head><meta name='viewport' content='width=device-width,initial-scale=1.0'></head>
            <body style='"margin:0;padding:0;"'><div>${widget.data}</div></body></html>
      """;
    }
    return widget.data;
  }

  InAppWebViewInitialData? requestData() {
    String? data = buildData();
    if(data.isNullOrEmpty) return null;
    return InAppWebViewInitialData(data: data!);
  }

  @override
  void didUpdateWidget(covariant T oldWidget) {
    super.didUpdateWidget(oldWidget);
    _updateController(webViewController);
  }

  void _updateController(InAppWebViewController? controller){
    webViewController = controller;
  }

  void _onTitleChanged(InAppWebViewController controller, String? title) => onTitleChanged(title!);
  void onTitleChanged(String title) {}
  void onOverScrolled(int x, int y,bool clampedX, bool clampedY){}
  void onScrollChanged(int x, int y){}
  void onLoadStop(Uri? url){}
  void onLongPressHitTestResult(InAppWebViewHitTestResult result){}

  printLogger(msg) {
    if(msg is ConsoleMessage) {
      ConsoleMessageLevel level = msg.messageLevel;
      if(level == ConsoleMessageLevel.WARNING) {
        logger.warn(msg.message);
      } else if(level == ConsoleMessageLevel.LOG) {
        logger.info(msg.message);
      } else if(level == ConsoleMessageLevel.DEBUG) {
        logger.debug(msg.message);
      } else if(level == ConsoleMessageLevel.ERROR) {
        logger.error(msg.message);
      } else {
        logger.error(msg.message);
      }
    } else {
      printLogger2(msg);
    }
  }
  printLogger2(msg) {
    debugPrint(msg.toString());
  }

  reload() => webViewController?.reload();

  Future<bool> canGoBack() {
    if(webViewController == null) return Future.value(false);
    return webViewController!.canGoBack();
  }

  Future<void> clearCache(){
    return InAppWebViewController.clearAllCache();
    // return webViewController?.clearCache();
  }

  Future goBack() async {
    return webViewController?.goBack();
  }
}